home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / MOR55SRC.ZIP / MORIA / SOURCE / MORIA1.C < prev    next >
C/C++ Source or Header  |  1992-12-07  |  45KB  |  1,848 lines

  1. /* source/moria1.c: misc code, mainly handles player movement, inventory, etc
  2.  
  3.    Copyright (c) 1989-92 James E. Wilson, Robert A. Koeneke
  4.  
  5.    This software may be copied and distributed for educational, research, and
  6.    not for profit purposes provided that this copyright and statement are
  7.    included in all such copies. */
  8.  
  9. #ifdef __TURBOC__
  10. #include    <stdlib.h>
  11. #endif
  12.  
  13. #include <stdio.h>
  14. #include <ctype.h>
  15.  
  16. #include "config.h"
  17. #include "constant.h"
  18. #include "types.h"
  19. #include "externs.h"
  20.  
  21. #ifdef USG
  22. #ifndef ATARIST_MWC
  23. #include <string.h>
  24. #else
  25. char *strcat();
  26. int strlen();
  27. #endif
  28. #else
  29. #include <strings.h>
  30. #endif
  31.  
  32. #if defined(LINT_ARGS)
  33. static void inven_screen(int);
  34. static char map_roguedir(char);
  35. static void sub1_move_light(int, int, int, int);
  36. static void sub3_move_light(int, int, int, int);
  37. #endif
  38.  
  39. #ifdef ATARIST_TC
  40. /* Include this to get prototypes for standard library functions.  */
  41. #include <stdlib.h>
  42. #endif
  43.  
  44. /* Changes speed of monsters relative to player        -RAK-    */
  45. /* Note: When the player is sped up or slowed down, I simply     */
  46. /*     change the speed of all the monsters.    This greatly     */
  47. /*     simplified the logic.                       */
  48. void change_speed(num)
  49. register int num;
  50. {
  51.   register int i;
  52. #ifdef ATARIST_MWC
  53.   int32u holder;
  54. #endif
  55.  
  56.   py.flags.speed += num;
  57. #ifdef ATARIST_MWC
  58.   py.flags.status |= (holder = PY_SPEED);
  59. #else
  60.   py.flags.status |= PY_SPEED;
  61. #endif
  62.   for (i = mfptr - 1; i >= MIN_MONIX; i--)
  63.       m_list[i].cspeed += num;
  64. }
  65.  
  66.  
  67. /* Player bonuses                    -RAK-    */
  68. /* When an item is worn or taken off, this re-adjusts the player */
  69. /* bonuses.  Factor=1 : wear; Factor=-1 : removed         */
  70. /* Only calculates properties with cumulative effect.  Properties that
  71.    depend on everything being worn are recalculated by calc_bonuses() -CJS- */
  72. void py_bonuses(t_ptr, factor)
  73. register inven_type *t_ptr;
  74. register int factor;
  75. {
  76.   register int i, amount;
  77. #ifdef ATARIST_MWC
  78.   int32u holder;
  79. #endif
  80.  
  81.   amount = t_ptr->p1 * factor;
  82.   if (t_ptr->flags & TR_STATS)
  83.     {
  84.       for(i = 0; i < 6; i++)
  85.     if ((1 << i) & t_ptr->flags)
  86.       bst_stat(i, amount);
  87.     }
  88.   if (TR_SEARCH & t_ptr->flags)
  89.     {
  90.       py.misc.srh += amount;
  91.       py.misc.fos -= amount;
  92.     }
  93.   if (TR_STEALTH & t_ptr->flags)
  94.     py.misc.stl += amount;
  95.   if (TR_SPEED & t_ptr->flags)
  96.     change_speed(-amount);
  97. #ifdef ATARIST_MWC
  98.   if (((holder = TR_BLIND) & t_ptr->flags) && (factor > 0))
  99.     py.flags.blind += 1000;
  100.   if (((holder = TR_TIMID) & t_ptr->flags) && (factor > 0))
  101.     py.flags.afraid += 50;
  102.   if ((holder = TR_INFRA) & t_ptr->flags)
  103.     py.flags.see_infra += amount;
  104. #else
  105.   if ((TR_BLIND & t_ptr->flags) && (factor > 0))
  106.     py.flags.blind += 1000;
  107.   if ((TR_TIMID & t_ptr->flags) && (factor > 0))
  108.     py.flags.afraid += 50;
  109.   if (TR_INFRA & t_ptr->flags)
  110.     py.flags.see_infra += amount;
  111. #endif
  112. }
  113.  
  114. /* Recalculate the effect of all the stuff we use.          -CJS- */
  115. void calc_bonuses()
  116. {
  117.   register int32u item_flags;
  118. #if defined(ATARIST_MWC)
  119.   int32u holder;        /* to avoid a compiler bug */
  120. #endif
  121.   int old_dis_ac;
  122.   register struct flags *p_ptr;
  123.   register struct misc *m_ptr;
  124.   register inven_type *i_ptr;
  125.   register int i;
  126.  
  127.   p_ptr = &py.flags;
  128.   m_ptr = &py.misc;
  129.   if (p_ptr->slow_digest)
  130.     p_ptr->food_digested++;
  131.   if (p_ptr->regenerate)
  132.     p_ptr->food_digested -= 3;
  133.   p_ptr->see_inv     = FALSE;
  134.   p_ptr->teleport    = FALSE;
  135.   p_ptr->free_act    = FALSE;
  136.   p_ptr->slow_digest = FALSE;
  137.   p_ptr->aggravate   = FALSE;
  138.   p_ptr->sustain_str = FALSE;
  139.   p_ptr->sustain_int = FALSE;
  140.   p_ptr->sustain_wis = FALSE;
  141.   p_ptr->sustain_con = FALSE;
  142.   p_ptr->sustain_dex = FALSE;
  143.   p_ptr->sustain_chr = FALSE;
  144.   p_ptr->fire_resist = FALSE;
  145.   p_ptr->acid_resist = FALSE;
  146.   p_ptr->cold_resist = FALSE;
  147.   p_ptr->regenerate  = FALSE;
  148.   p_ptr->lght_resist = FALSE;
  149.   p_ptr->ffall         = FALSE;
  150.  
  151.   old_dis_ac = m_ptr->dis_ac;
  152.   m_ptr->ptohit     = tohit_adj();          /* Real To Hit   */
  153.   m_ptr->ptodam     = todam_adj();          /* Real To Dam   */
  154.   m_ptr->ptoac     = toac_adj();          /* Real To AC    */
  155.   m_ptr->pac     = 0;            /* Real AC         */
  156.   m_ptr->dis_th     = m_ptr->ptohit;  /* Display To Hit        */
  157.   m_ptr->dis_td     = m_ptr->ptodam;  /* Display To Dam        */
  158.   m_ptr->dis_ac     = 0;        /* Display AC         */
  159.   m_ptr->dis_tac = m_ptr->ptoac;   /* Display To AC        */
  160.   for (i = INVEN_WIELD; i < INVEN_LIGHT; i++)
  161.     {
  162.       i_ptr = &inventory[i];
  163.       if (i_ptr->tval != TV_NOTHING)
  164.     {
  165.       m_ptr->ptohit += i_ptr->tohit;
  166.       if (i_ptr->tval != TV_BOW)        /* Bows can't damage. -CJS- */
  167.         m_ptr->ptodam += i_ptr->todam;
  168.       m_ptr->ptoac    += i_ptr->toac;
  169.       m_ptr->pac += i_ptr->ac;
  170.       if (known2_p(i_ptr))
  171.         {
  172.           m_ptr->dis_th  += i_ptr->tohit;
  173.           if (i_ptr->tval != TV_BOW)
  174.         m_ptr->dis_td  += i_ptr->todam;    /* Bows can't damage. -CJS- */
  175.           m_ptr->dis_tac += i_ptr->toac;
  176.           m_ptr->dis_ac += i_ptr->ac;
  177.         }
  178.       else if (! (TR_CURSED & i_ptr->flags))
  179.         /* Base AC values should always be visible, as long as the item
  180.            is not cursed.  */
  181.         m_ptr->dis_ac += i_ptr->ac;
  182.     }
  183.     }
  184.   m_ptr->dis_ac += m_ptr->dis_tac;
  185.  
  186.   if (weapon_heavy)
  187.     m_ptr->dis_th += (py.stats.use_stat[A_STR] * 15 -
  188.               inventory[INVEN_WIELD].weight);
  189.  
  190.   /* Add in temporary spell increases    */
  191.   if (p_ptr->invuln > 0)
  192.     {
  193.       m_ptr->pac += 100;
  194.       m_ptr->dis_ac += 100;
  195.     }
  196.   if (p_ptr->blessed > 0)
  197.     {
  198.       m_ptr->pac    += 2;
  199.       m_ptr->dis_ac += 2;
  200.     }
  201.   if (p_ptr->detect_inv > 0)
  202.     p_ptr->see_inv = TRUE;
  203.  
  204.   /* can't print AC here because might be in a store */
  205.   if (old_dis_ac != m_ptr->dis_ac)
  206. #ifdef ATARIST_MWC
  207.     p_ptr->status |= (holder = PY_ARMOR);
  208. #else
  209.     p_ptr->status |= PY_ARMOR;
  210. #endif
  211.  
  212.   item_flags = 0;
  213.   i_ptr = &inventory[INVEN_WIELD];
  214.   for (i = INVEN_WIELD; i < INVEN_LIGHT; i++)
  215.     {
  216.       item_flags |= i_ptr->flags;
  217.       i_ptr++;
  218.     }
  219. #if !defined(ATARIST_MWC)
  220.   if (TR_SLOW_DIGEST & item_flags)
  221.     p_ptr->slow_digest = TRUE;
  222.   if (TR_AGGRAVATE & item_flags)
  223.     p_ptr->aggravate = TRUE;
  224.   if (TR_TELEPORT & item_flags)
  225.     p_ptr->teleport = TRUE;
  226.   if (TR_REGEN & item_flags)
  227.     p_ptr->regenerate = TRUE;
  228.   if (TR_RES_FIRE & item_flags)
  229.     p_ptr->fire_resist = TRUE;
  230.   if (TR_RES_ACID & item_flags)
  231.     p_ptr->acid_resist = TRUE;
  232.   if (TR_RES_COLD & item_flags)
  233.     p_ptr->cold_resist = TRUE;
  234.   if (TR_FREE_ACT & item_flags)
  235.     p_ptr->free_act = TRUE;
  236.   if (TR_SEE_INVIS & item_flags)
  237.     p_ptr->see_inv = TRUE;
  238.   if (TR_RES_LIGHT & item_flags)
  239.     p_ptr->lght_resist = TRUE;
  240.   if (TR_FFALL & item_flags)
  241.     p_ptr->ffall = TRUE;
  242. #else
  243.   /* this avoids a bug in the Mark Williams C compiler for the Atari ST */
  244.   holder = TR_SLOW_DIGEST;
  245.   if (holder & item_flags)
  246.     p_ptr->slow_digest = TRUE;
  247.   holder = TR_AGGRAVATE;
  248.   if (holder & item_flags)
  249.     p_ptr->aggravate = TRUE;
  250.   holder = TR_TELEPORT;
  251.   if (holder & item_flags)
  252.     p_ptr->teleport = TRUE;
  253.   holder = TR_REGEN;
  254.   if (holder & item_flags)
  255.     p_ptr->regenerate = TRUE;
  256.   holder = TR_RES_FIRE;
  257.   if (holder & item_flags)
  258.     p_ptr->fire_resist = TRUE;
  259.   holder = TR_RES_ACID;
  260.   if (holder & item_flags)
  261.     p_ptr->acid_resist = TRUE;
  262.   holder = TR_RES_COLD;
  263.   if (holder & item_flags)
  264.     p_ptr->cold_resist = TRUE;
  265.   holder = TR_FREE_ACT;
  266.   if (holder & item_flags)
  267.     p_ptr->free_act = TRUE;
  268.   holder = TR_SEE_INVIS;
  269.   if (holder & item_flags)
  270.     p_ptr->see_inv = TRUE;
  271.   holder = TR_RES_LIGHT;
  272.   if (holder & item_flags)
  273.     p_ptr->lght_resist = TRUE;
  274.   holder = TR_FFALL;
  275.   if (holder & item_flags)
  276.     p_ptr->ffall = TRUE;
  277. #endif
  278.  
  279.   i_ptr = &inventory[INVEN_WIELD];
  280.   for (i = INVEN_WIELD; i < INVEN_LIGHT; i++)
  281.     {
  282. #ifdef ATARIST_MWC
  283.       if ((holder = TR_SUST_STAT) & i_ptr->flags)
  284. #else
  285.       if (TR_SUST_STAT & i_ptr->flags)
  286. #endif
  287.     switch(i_ptr->p1)
  288.       {
  289.       case 1: p_ptr->sustain_str = TRUE; break;
  290.       case 2: p_ptr->sustain_int = TRUE; break;
  291.       case 3: p_ptr->sustain_wis = TRUE; break;
  292.       case 4: p_ptr->sustain_con = TRUE; break;
  293.       case 5: p_ptr->sustain_dex = TRUE; break;
  294.       case 6: p_ptr->sustain_chr = TRUE; break;
  295.       default: break;
  296.       }
  297.       i_ptr++;
  298.     }
  299.  
  300.   if (p_ptr->slow_digest)
  301.     p_ptr->food_digested--;
  302.   if (p_ptr->regenerate)
  303.     p_ptr->food_digested += 3;
  304. }
  305.  
  306.  
  307. /* Displays inventory items from r1 to r2    -RAK-    */
  308. /* Designed to keep the display as far to the right as possible.  The  -CJS-
  309.    parameter col gives a column at which to start, but if the display does
  310.    not fit, it may be moved left.  The return value is the left edge used. */
  311. /* If mask is non-zero, then only display those items which have a non-zero
  312.    entry in the mask array.  */
  313. int show_inven(r1, r2, weight, col, mask)
  314. register int r1, r2;
  315. int weight, col;
  316. char *mask;
  317. {
  318.   register int i;
  319.   int total_weight, len, l, lim, current_line;
  320.   bigvtype tmp_val;
  321.   vtype out_val[23];
  322.  
  323.   len = 79 - col;
  324.   if (weight)
  325.     lim = 68;
  326.   else
  327.     lim = 76;
  328.  
  329.   for (i = r1; i <= r2; i++)         /* Print the items      */
  330.     {
  331.       if (mask == CNIL || mask[i])
  332.     {
  333.       objdes(tmp_val, &inventory[i], TRUE);
  334.       tmp_val[lim] = 0;     /* Truncate if too long. */
  335.       (void) sprintf(out_val[i], "  %c) %s", 'a'+i, tmp_val);
  336.       l = strlen(out_val[i]);
  337.       if (weight)
  338.         l += 9;
  339.       if (l > len)
  340.         len = l;
  341.     }
  342.     }
  343.  
  344.   col = 79 - len;
  345.   if (col < 0)
  346.     col = 0;
  347.  
  348.   current_line = 1;
  349.   for (i = r1; i <= r2; i++)
  350.     {
  351.       if (mask == CNIL || mask[i])
  352.     {
  353.       /* don't need first two spaces if in first column */
  354.       if (col == 0)
  355.         prt(&out_val[i][2], current_line, col);
  356.       else
  357.         prt(out_val[i], current_line, col);
  358.       if (weight)
  359.         {
  360.           total_weight = inventory[i].weight*inventory[i].number;
  361.           (void) sprintf (tmp_val, "%3d.%d lb",
  362.                   (total_weight) / 10, (total_weight) % 10);
  363.           prt (tmp_val, current_line, 71);
  364.         }
  365.       current_line++;
  366.     }
  367.     }
  368.   return col;
  369. }
  370.  
  371.  
  372. /* Return a string describing how a given equipment item is carried. -CJS- */
  373. char *describe_use(i)
  374. register int i;
  375. {
  376.   register char *p;
  377.  
  378.   switch(i)
  379.     {
  380.     case INVEN_WIELD:
  381.       p = "wielding"; break;
  382.     case INVEN_HEAD:
  383.       p = "wearing on your head"; break;
  384.     case INVEN_NECK:
  385.       p = "wearing around your neck"; break;
  386.     case INVEN_BODY:
  387.       p = "wearing on your body"; break;
  388.     case INVEN_ARM:
  389.       p = "wearing on your arm"; break;
  390.     case INVEN_HANDS:
  391.       p = "wearing on your hands"; break;
  392.     case INVEN_RIGHT:
  393.       p = "wearing on your right hand"; break;
  394.     case INVEN_LEFT:
  395.       p = "wearing on your left hand"; break;
  396.     case INVEN_FEET:
  397.       p = "wearing on your feet"; break;
  398.     case INVEN_OUTER:
  399.       p = "wearing about your body"; break;
  400.     case INVEN_LIGHT:
  401.       p = "using to light the way"; break;
  402.     case INVEN_AUX:
  403.       p = "holding ready by your side"; break;
  404.     default:
  405.       p = "carrying in your pack"; break;
  406.     }
  407.   return p;
  408. }
  409.  
  410.  
  411. /* Displays equipment items from r1 to end    -RAK-    */
  412. /* Keep display as far right as possible. -CJS- */
  413. int show_equip(weight, col)
  414. int weight, col;
  415. {
  416.   register int i, line;
  417.   int total_weight, l, len, lim;
  418.   register char *prt1;
  419.   bigvtype prt2;
  420.   vtype out_val[INVEN_ARRAY_SIZE-INVEN_WIELD];
  421.   register inven_type *i_ptr;
  422.  
  423.   line = 0;
  424.   len = 79 - col;
  425.   if (weight)
  426.     lim = 52;
  427.   else
  428.     lim = 60;
  429.   for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++) /* Range of equipment */
  430.     {
  431.       i_ptr = &inventory[i];
  432.       if (i_ptr->tval != TV_NOTHING)
  433.     {
  434.       switch(i)         /* Get position          */
  435.         {
  436.         case INVEN_WIELD:
  437.           if (py.stats.use_stat[A_STR]*15 < i_ptr->weight)
  438.         prt1 = "Just lifting";
  439.           else
  440.         prt1 = "Wielding";
  441.           break;
  442.         case INVEN_HEAD:
  443.           prt1 = "On head"; break;
  444.         case INVEN_NECK:
  445.           prt1 = "Around neck"; break;
  446.         case INVEN_BODY:
  447.           prt1 = "On body"; break;
  448.         case INVEN_ARM:
  449.           prt1 = "On arm"; break;
  450.         case INVEN_HANDS:
  451.           prt1 = "On hands"; break;
  452.         case INVEN_RIGHT:
  453.           prt1 = "On right hand"; break;
  454.         case INVEN_LEFT:
  455.           prt1 = "On left hand"; break;
  456.         case INVEN_FEET:
  457.           prt1 = "On feet"; break;
  458.         case INVEN_OUTER:
  459.           prt1 = "About body"; break;
  460.         case INVEN_LIGHT:
  461.           prt1 = "Light source"; break;
  462.         case INVEN_AUX:
  463.           prt1 = "Spare weapon"; break;
  464.         default:
  465.           prt1 = "Unknown value"; break;
  466.         }
  467.       objdes(prt2, &inventory[i], TRUE);
  468.       prt2[lim] = 0; /* Truncate if necessary */
  469.       (void) sprintf(out_val[line], "  %c) %-14s: %s", line+'a',
  470.              prt1, prt2);
  471.       l = strlen(out_val[line]);
  472.       if (weight)
  473.         l += 9;
  474.       if (l > len)
  475.         len = l;
  476.       line++;
  477.     }
  478.     }
  479.   col = 79 - len;
  480.   if (col < 0)
  481.     col = 0;
  482.  
  483.   line = 0;
  484.   for (i = INVEN_WIELD; i < INVEN_ARRAY_SIZE; i++) /* Range of equipment */
  485.     {
  486.       i_ptr = &inventory[i];
  487.       if (i_ptr->tval != TV_NOTHING)
  488.     {
  489.       /* don't need first two spaces when using whole screen */
  490.       if (col == 0)
  491.         prt(&out_val[line][2], line+1, col);
  492.       else
  493.         prt(out_val[line], line+1, col);
  494.       if (weight)
  495.         {
  496.           total_weight = i_ptr->weight*i_ptr->number;
  497.           (void) sprintf(prt2, "%3d.%d lb",
  498.                  (total_weight) / 10, (total_weight) % 10);
  499.           prt(prt2, line+1, 71);
  500.         }
  501.       line++;
  502.     }
  503.     }
  504.   erase_line(line+1, col);
  505.   return col;
  506. }
  507.  
  508. /* Remove item from equipment list        -RAK-    */
  509. void takeoff(item_val, posn)
  510. int item_val, posn;
  511. {
  512.   register char *p;
  513.   bigvtype out_val, prt2;
  514.   register inven_type *t_ptr;
  515. #ifdef ATARIST_MWC
  516.   int32u holder;
  517. #endif
  518.  
  519.   equip_ctr--;
  520.   t_ptr = &inventory[item_val];
  521.   inven_weight -= t_ptr->weight*t_ptr->number;
  522. #ifdef ATARIST_MWC
  523.   py.flags.status |= (holder = PY_STR_WGT);
  524. #else
  525.   py.flags.status |= PY_STR_WGT;
  526. #endif
  527.  
  528.   if (item_val == INVEN_WIELD || item_val == INVEN_AUX)
  529.     p = "Was wielding ";
  530.   else if (item_val == INVEN_LIGHT)
  531.     p = "Light source was ";
  532.   else
  533.     p = "Was wearing ";
  534.  
  535.   objdes(prt2, t_ptr, TRUE);
  536.   if (posn >= 0)
  537.     (void) sprintf(out_val, "%s%s (%c)", p, prt2, 'a'+posn);
  538.   else
  539.     (void) sprintf(out_val, "%s%s", p, prt2);
  540.   msg_print(out_val);
  541.   if (item_val != INVEN_AUX)      /* For secondary weapon  */
  542.     py_bonuses(t_ptr, -1);
  543.   invcopy(t_ptr, OBJ_NOTHING);
  544. }
  545.  
  546.  
  547. /* Used to verify if this really is the item we wish to     -CJS-
  548.    wear or read. */
  549. int verify(prompt, item)
  550. char *prompt;
  551. int item;
  552. {
  553.   bigvtype out_str, object;
  554.  
  555.   objdes(object, &inventory[item], TRUE);
  556.   object[strlen(object)-1] = '?'; /* change the period to a question mark */
  557.   (void) sprintf(out_str, "%s %s", prompt, object);
  558.   return get_check(out_str);
  559. }
  560.  
  561.  
  562. /* All inventory commands (wear, exchange, take off, drop, inventory and
  563.    equipment) are handled in an alternative command input mode, which accepts
  564.    any of the inventory commands.
  565.  
  566.    It is intended that this function be called several times in succession,
  567.    as some commands take up a turn, and the rest of moria must proceed in the
  568.    interim. A global variable is provided, doing_inven, which is normally
  569.    zero; however if on return from inven_command it is expected that
  570.    inven_command should be called *again*, (being still in inventory command
  571.    input mode), then doing_inven is set to the inventory command character
  572.    which should be used in the next call to inven_command.
  573.  
  574.    On return, the screen is restored, but not flushed. Provided no flush of
  575.    the screen takes place before the next call to inven_command, the inventory
  576.    command screen is silently redisplayed, and no actual output takes place at
  577.    all. If the screen is flushed before a subsequent call, then the player is
  578.    prompted to see if we should continue. This allows the player to see any
  579.    changes that take place on the screen during inventory command input.
  580.  
  581.   The global variable, screen_change, is cleared by inven_command, and set
  582.   when the screen is flushed. This is the means by which inven_command tell
  583.   if the screen has been flushed.
  584.  
  585.   The display of inventory items is kept to the right of the screen to
  586.   minimize the work done to restore the screen afterwards.        -CJS-*/
  587.  
  588. /* Inventory command screen states. */
  589. #define BLANK_SCR    0
  590. #define EQUIP_SCR    1
  591. #define INVEN_SCR    2
  592. #define WEAR_SCR    3
  593. #define HELP_SCR    4
  594. #define WRONG_SCR    5
  595.  
  596. /* Keep track of the state of the inventory screen. */
  597. static int scr_state, scr_left, scr_base;
  598. static int wear_low, wear_high;
  599.  
  600. /* Draw the inventory screen. */
  601. static void inven_screen(new_scr)
  602. int new_scr;
  603. {
  604.   register int line;
  605.  
  606.   if (new_scr != scr_state)
  607.     {
  608.       scr_state = new_scr;
  609.       switch(new_scr)
  610.     {
  611.     case BLANK_SCR:
  612.       line = 0;
  613.       break;
  614.     case HELP_SCR:
  615.       if (scr_left > 52)
  616.         scr_left = 52;
  617.       prt("  ESC: exit", 1, scr_left);
  618.       prt("  w  : wear or wield object", 2, scr_left);
  619.       prt("  t  : take off item", 3, scr_left);
  620.       prt("  d  : drop object", 4, scr_left);
  621.       prt("  x  : exchange weapons", 5, scr_left);
  622.       prt("  i  : inventory of pack", 6, scr_left);
  623.       prt("  e  : list used equipment", 7, scr_left);
  624.       line = 7;
  625.       break;
  626.     case INVEN_SCR:
  627.       scr_left = show_inven(0, inven_ctr - 1, show_weight_flag, scr_left,
  628.                 CNIL);
  629.       line = inven_ctr;
  630.       break;
  631.     case WEAR_SCR:
  632.       scr_left = show_inven(wear_low, wear_high, show_weight_flag,
  633.                 scr_left, CNIL);
  634.       line = wear_high - wear_low + 1;
  635.       break;
  636.     case EQUIP_SCR:
  637.       scr_left = show_equip(show_weight_flag, scr_left);
  638.       line = equip_ctr;
  639.       break;
  640.     }
  641.       if (line >= scr_base)
  642.     {
  643.       scr_base = line + 1;
  644.       erase_line(scr_base, scr_left);
  645.     }
  646.       else
  647.     {
  648.       while (++line <= scr_base)
  649.         erase_line(line, scr_left);
  650.     }
  651.     }
  652. }
  653.  
  654. /* This does all the work. */
  655. void inven_command(command)
  656. char command;
  657. {
  658.   register int slot, item;
  659.   int tmp, tmp2, selecting, from, to;
  660.   char *prompt, *swap, *disp, *string;
  661.   char which, query;
  662.   bigvtype prt1, prt2;
  663.   register inven_type *i_ptr;
  664.   inven_type tmp_obj;
  665. #ifdef ATARIST_MWC
  666.   int32u holder;
  667. #endif
  668.  
  669.   free_turn_flag = TRUE;
  670.   save_screen();
  671.   /* Take up where we left off after a previous inventory command. -CJS- */
  672.   if (doing_inven)
  673.     {
  674.       /* If the screen has been flushed, we need to redraw. If the command is
  675.      a simple ' ' to recover the screen, just quit. Otherwise, check and
  676.      see what the user wants. */
  677.       if (screen_change)
  678.     {
  679.       if (command == ' ' || !get_check("Continuing with inventory command?"))
  680.         {
  681.           doing_inven = FALSE;
  682.           return;
  683.         }
  684.       scr_left = 50;
  685.       scr_base = 0;
  686.     }
  687.       tmp = scr_state;
  688.       scr_state = WRONG_SCR;
  689.       inven_screen(tmp);
  690.     }
  691.   else
  692.     {
  693.       scr_left = 50;
  694.       scr_base = 0;
  695.       /* this forces exit of inven_command() if selecting is not set true */
  696.       scr_state = BLANK_SCR;
  697.     }
  698.   do
  699.     {
  700.       if (isupper((int)command))
  701.     command = tolower((int)command);
  702.  
  703.       /* Simple command getting and screen selection. */
  704.       selecting = FALSE;
  705.       switch(command)
  706.     {
  707.     case 'i':       /* Inventory        */
  708.       if (inven_ctr == 0)
  709.         msg_print("You are not carrying anything.");
  710.       else
  711.         inven_screen(INVEN_SCR);
  712.       break;
  713.     case 'e':      /* Equipment       */
  714.       if (equip_ctr == 0)
  715.         msg_print("You are not using any equipment.");
  716.       else
  717.         inven_screen(EQUIP_SCR);
  718.       break;
  719.     case 't':      /* Take off       */
  720.       if (equip_ctr == 0)
  721.         msg_print("You are not using any equipment.");
  722.       /* don't print message restarting inven command after taking off
  723.          something, it is confusing */
  724.       else if (inven_ctr >= INVEN_WIELD && !doing_inven)
  725.         msg_print("You will have to drop something first.");
  726.       else
  727.         {
  728.           if (scr_state != BLANK_SCR)
  729.         inven_screen(EQUIP_SCR);
  730.           selecting = TRUE;
  731.         }
  732.       break;
  733.     case 'd':        /* Drop */
  734.       if (inven_ctr == 0 && equip_ctr == 0)
  735.         msg_print("But you're not carrying anything.");
  736.       else if (cave[char_row][char_col].tptr != 0)
  737.         msg_print("There's no room to drop anything here.");
  738.       else
  739.         {
  740.           selecting = TRUE;
  741.           if ((scr_state == EQUIP_SCR && equip_ctr > 0) || inven_ctr == 0)
  742.         {
  743.           if (scr_state != BLANK_SCR)
  744.             inven_screen(EQUIP_SCR);
  745.           command = 'r';    /* Remove - or take off and drop. */
  746.         }
  747.           else if (scr_state != BLANK_SCR)
  748.         inven_screen(INVEN_SCR);
  749.         }
  750.       break;
  751.     case 'w':      /* Wear/wield       */
  752.       for (wear_low = 0;
  753.            wear_low < inven_ctr && inventory[wear_low].tval > TV_MAX_WEAR;
  754.            wear_low++)
  755.         ;
  756.       for(wear_high = wear_low;
  757.           wear_high < inven_ctr && inventory[wear_high].tval >=TV_MIN_WEAR;
  758.           wear_high++)
  759.         ;
  760.       wear_high--;
  761.       if (wear_low > wear_high)
  762.         msg_print("You have nothing to wear or wield.");
  763.       else
  764.         {
  765.           if (scr_state != BLANK_SCR && scr_state != INVEN_SCR)
  766.         inven_screen(WEAR_SCR);
  767.           selecting = TRUE;
  768.         }
  769.       break;
  770.     case 'x':
  771.       if (inventory[INVEN_WIELD].tval == TV_NOTHING &&
  772.           inventory[INVEN_AUX].tval == TV_NOTHING)
  773.         msg_print("But you are wielding no weapons.");
  774. #ifdef ATARIST_MWC
  775.       else if ((holder = TR_CURSED) & inventory[INVEN_WIELD].flags)
  776. #else
  777.       else if (TR_CURSED & inventory[INVEN_WIELD].flags)
  778. #endif
  779.         {
  780.           objdes(prt1, &inventory[INVEN_WIELD], FALSE);
  781.           (void) sprintf(prt2,
  782.              "The %s you are wielding appears to be cursed.", prt1);
  783.           msg_print(prt2);
  784.         }
  785.       else
  786.         {
  787.           free_turn_flag = FALSE;
  788.           tmp_obj = inventory[INVEN_AUX];
  789.           inventory[INVEN_AUX] = inventory[INVEN_WIELD];
  790.           inventory[INVEN_WIELD] = tmp_obj;
  791.           if (scr_state == EQUIP_SCR)
  792.         scr_left = show_equip(show_weight_flag, scr_left);
  793.           py_bonuses(&inventory[INVEN_AUX], -1);     /* Subtract bonuses */
  794.           py_bonuses(&inventory[INVEN_WIELD], 1);       /* Add bonuses    */
  795.           if (inventory[INVEN_WIELD].tval != TV_NOTHING)
  796.         {
  797.           (void) strcpy(prt1, "Primary weapon   : ");
  798.           objdes(prt2, &inventory[INVEN_WIELD], TRUE);
  799.           msg_print(strcat(prt1, prt2));
  800.         }
  801.           else
  802.         msg_print("No primary weapon.");
  803.           /* this is a new weapon, so clear the heavy flag */
  804.           weapon_heavy = FALSE;
  805.           check_strength();
  806.         }
  807.       break;
  808.     case ' ':    /* Dummy command to return again to main prompt. */
  809.       break;
  810.     case '?':
  811.       inven_screen(HELP_SCR);
  812.       break;
  813.     default:
  814.       /* Nonsense command                       */
  815.       bell();
  816.       break;
  817.     }
  818.  
  819.       /* Clear the doing_inven flag here, instead of at beginning, so that
  820.      can use it to control when messages above appear. */
  821.       doing_inven = 0;
  822.  
  823.       /* Keep looking for objects to drop/wear/take off/throw off */
  824.       which = 'z';
  825.       while (selecting && free_turn_flag)
  826.     {
  827.       swap = "";
  828.       if (command == 'w')
  829.         {
  830.           from = wear_low;
  831.           to = wear_high;
  832.           prompt = "Wear/Wield";
  833.         }
  834.       else
  835.         {
  836.           from = 0;
  837.           if (command == 'd')
  838.         {
  839.           to = inven_ctr - 1;
  840.           prompt = "Drop";
  841.           if (equip_ctr > 0)
  842.             swap = ", / for Equip";
  843.         }
  844.           else
  845.         {
  846.           to = equip_ctr - 1;
  847.           if (command == 't')
  848.             prompt = "Take off";
  849.           else    /* command == 'r' */
  850.             {
  851.               prompt = "Throw off";
  852.               if (inven_ctr > 0)
  853.             swap = ", / for Inven";
  854.             }
  855.         }
  856.         }
  857.       if (from > to)
  858.         selecting = FALSE;
  859.       else
  860.         {
  861.           if (scr_state == BLANK_SCR)
  862.         disp = ", * to list";
  863.           else
  864.         disp = "";
  865.           (void) sprintf(prt1,
  866.               "(%c-%c%s%s, space to break, ESC to exit) %s which one?",
  867.               from+'a', to+'a', disp, swap, prompt);
  868.  
  869.           /* Abort everything. */
  870.           if (!get_com(prt1, &which))
  871.         {
  872.           selecting = FALSE;
  873.           which = ESCAPE;
  874.         }
  875.           /* Draw the screen and maybe exit to main prompt. */
  876.           else if (which == ' ' || which == '*')
  877.         {
  878.           if (command == 't' || command == 'r')
  879.             inven_screen(EQUIP_SCR);
  880.           else if (command == 'w' && scr_state != INVEN_SCR)
  881.             inven_screen(WEAR_SCR);
  882.           else
  883.             inven_screen(INVEN_SCR);
  884.           if (which == ' ')
  885.             selecting = FALSE;
  886.         }
  887.           /* Swap screens (for drop) */
  888.           else if (which == '/' && swap[0])
  889.         {
  890.           if (command == 'd')
  891.             command = 'r';
  892.           else
  893.             command = 'd';
  894.           if (scr_state == EQUIP_SCR)
  895.             inven_screen(INVEN_SCR);
  896.           else if (scr_state == INVEN_SCR)
  897.             inven_screen(EQUIP_SCR);
  898.         }
  899.           else if ((which < from + 'a' || which > to + 'a')
  900.                && (which < from + 'A' || which > to + 'A'))
  901.         bell();
  902.           else  /* Found an item! */
  903.         {
  904.           if (isupper((int)which))
  905.             item = which - 'A';
  906.           else
  907.             item = which - 'a';
  908.           if (command == 'r' || command == 't')
  909.             {
  910.               /* Get its place in the equipment list. */
  911.               tmp = item;
  912.               item = 21;
  913.               do
  914.             {
  915.               item++;
  916.               if (inventory[item].tval != TV_NOTHING)
  917.                 tmp--;
  918.             }
  919.               while (tmp >= 0);
  920.               if (isupper((int)which) && !verify(prompt, item))
  921.             item = -1;
  922. #ifdef ATARIST_MWC
  923.               else if ((holder = TR_CURSED) & inventory[item].flags)
  924. #else
  925.               else if (TR_CURSED & inventory[item].flags)
  926. #endif
  927.             {
  928.               msg_print("Hmmm, it seems to be cursed.");
  929.               item = -1;
  930.             }
  931.               else if (command == 't' &&
  932.                    !inven_check_num(&inventory[item]))
  933.             {
  934.               if (cave[char_row][char_col].tptr != 0)
  935.                 {
  936.                   msg_print("You can't carry it.");
  937.                   item = -1;
  938.                 }
  939.               else if (get_check("You can't carry it.  Drop it?"))
  940.                 command = 'r';
  941.               else
  942.                 item = -1;
  943.             }
  944.               if (item >= 0)
  945.             {
  946.               if (command == 'r')
  947.                 {
  948.                   inven_drop(item, TRUE);
  949.                   /* As a safety measure, set the player's inven
  950.                  weight to 0, when the last object is dropped*/
  951.                   if (inven_ctr == 0 && equip_ctr == 0)
  952.                 inven_weight = 0;
  953.                 }
  954.               else
  955.                 {
  956.                   slot = inven_carry(&inventory[item]);
  957.                   takeoff(item, slot);
  958.                 }
  959.               check_strength();
  960.               free_turn_flag = FALSE;
  961.               if (command == 'r')
  962.                 selecting = FALSE;
  963.             }
  964.             }
  965.           else if (command == 'w')
  966.             {
  967.               /* Wearing. Go to a bit of trouble over replacing
  968.              existing equipment. */
  969.               if (isupper((int)which) && !verify(prompt, item))
  970.             item = -1;
  971.               else switch(inventory[item].tval)
  972.             { /* Slot for equipment       */
  973.             case TV_SLING_AMMO: case TV_BOLT: case TV_ARROW:
  974.             case TV_BOW: case TV_HAFTED: case TV_POLEARM:
  975.             case TV_SWORD: case TV_DIGGING: case TV_SPIKE:
  976.               slot = INVEN_WIELD; break;
  977.             case TV_LIGHT: slot = INVEN_LIGHT; break;
  978.             case TV_BOOTS: slot = INVEN_FEET; break;
  979.             case TV_GLOVES: slot = INVEN_HANDS; break;
  980.             case TV_CLOAK: slot = INVEN_OUTER; break;
  981.             case TV_HELM: slot = INVEN_HEAD; break;
  982.             case TV_SHIELD: slot = INVEN_ARM; break;
  983.             case TV_HARD_ARMOR: case TV_SOFT_ARMOR:
  984.               slot = INVEN_BODY; break;
  985.             case TV_AMULET: slot = INVEN_NECK; break;
  986.             case TV_RING:
  987.               if (inventory[INVEN_RIGHT].tval == TV_NOTHING)
  988.                 slot = INVEN_RIGHT;
  989.               else if (inventory[INVEN_LEFT].tval == TV_NOTHING)
  990.                 slot = INVEN_LEFT;
  991.               else
  992.                 {
  993.                   slot = 0;
  994.                   /* Rings. Give some choice over where they go. */
  995.                   do
  996.                 {
  997.                   if (!get_com(
  998.                    "Put ring on which hand (l/r/L/R)?", &query))
  999.                     {
  1000.                       item = -1;
  1001.                       slot = -1;
  1002.                     }
  1003.                   else if (query == 'l')
  1004.                     slot = INVEN_LEFT;
  1005.                   else if (query == 'r')
  1006.                     slot = INVEN_RIGHT;
  1007.                   else
  1008.                     {
  1009.                       if (query == 'L')
  1010.                     slot = INVEN_LEFT;
  1011.                       else if (query == 'R')
  1012.                     slot = INVEN_RIGHT;
  1013.                       else
  1014.                     bell();
  1015.                       if (slot && !verify("Replace", slot))
  1016.                     slot = 0;
  1017.                     }
  1018.                 }
  1019.                   while(slot == 0);
  1020.                 }
  1021.               break;
  1022.             default:
  1023.           msg_print("IMPOSSIBLE: I don't see how you can use that.");
  1024.               item = -1;
  1025.               break;
  1026.             }
  1027.               if (item >= 0 && inventory[slot].tval != TV_NOTHING)
  1028.             {
  1029. #ifdef ATARIST_MWC
  1030.               if ((holder = TR_CURSED) & inventory[slot].flags)
  1031. #else
  1032.               if (TR_CURSED & inventory[slot].flags)
  1033. #endif
  1034.                 {
  1035.                   objdes(prt1, &inventory[slot], FALSE);
  1036.                   (void) sprintf(prt2, "The %s you are ", prt1);
  1037.                   if (slot == INVEN_HEAD)
  1038.                 (void) strcat(prt2, "wielding ");
  1039.                   else
  1040.                 (void) strcat(prt2, "wearing ");
  1041.                   msg_print(strcat(prt2, "appears to be cursed."));
  1042.                   item = -1;
  1043.                 }
  1044.               else if (inventory[item].subval == ITEM_GROUP_MIN &&
  1045.                    inventory[item].number > 1 &&
  1046.                    !inven_check_num(&inventory[slot]))
  1047.                 {
  1048.                   /* this can happen if try to wield a torch, and
  1049.                  have more than one in your inventory */
  1050.                msg_print("You will have to drop something first.");
  1051.                   item = -1;
  1052.                 }
  1053.             }
  1054.               if (item >= 0)
  1055.             {
  1056.               /* OK. Wear it. */
  1057.               free_turn_flag = FALSE;
  1058.  
  1059.               /* first remove new item from inventory */
  1060.               tmp_obj = inventory[item];
  1061.               i_ptr = &tmp_obj;
  1062.  
  1063.               wear_high--;
  1064.               /* Fix for torches       */
  1065.               if (i_ptr->number > 1
  1066.                   && i_ptr->subval <= ITEM_SINGLE_STACK_MAX)
  1067.                 {
  1068.                   i_ptr->number = 1;
  1069.                   wear_high++;
  1070.                 }
  1071.               inven_weight += i_ptr->weight*i_ptr->number;
  1072.               inven_destroy(item);    /* Subtracts weight */
  1073.  
  1074.               /* second, add old item to inv and remove from
  1075.                  equipment list, if necessary */
  1076.               i_ptr = &inventory[slot];
  1077.               if (i_ptr->tval != TV_NOTHING)
  1078.                 {
  1079.                   tmp2 = inven_ctr;
  1080.                   tmp = inven_carry(i_ptr);
  1081.                   /* if item removed did not stack with anything in
  1082.                  inventory, then increment wear_high */
  1083.                   if (inven_ctr != tmp2)
  1084.                 wear_high++;
  1085.                   takeoff(slot, tmp);
  1086.                 }
  1087.  
  1088.               /* third, wear new item */
  1089.               *i_ptr = tmp_obj;
  1090.               equip_ctr++;
  1091.               py_bonuses(i_ptr, 1);
  1092.               if (slot == INVEN_WIELD)
  1093.                 string = "You are wielding";
  1094.               else if (slot == INVEN_LIGHT)
  1095.                 string = "Your light source is";
  1096.               else
  1097.                 string = "You are wearing";
  1098.               objdes(prt2, i_ptr, TRUE);
  1099.               /* Get the right equipment letter. */
  1100.               tmp = INVEN_WIELD;
  1101.               item = 0;
  1102.               while (tmp != slot)
  1103.                 if (inventory[tmp++].tval != TV_NOTHING)
  1104.                   item++;
  1105.  
  1106.               (void) sprintf(prt1, "%s %s (%c)", string, prt2,
  1107.                      'a'+item);
  1108.               msg_print(prt1);
  1109.               /* this is a new weapon, so clear the heavy flag */
  1110.               if (slot == INVEN_WIELD)
  1111.                 weapon_heavy = FALSE;
  1112.               check_strength();
  1113. #ifdef ATARIST_MWC
  1114.               if (i_ptr->flags & (holder = TR_CURSED))
  1115. #else
  1116.               if (i_ptr->flags & TR_CURSED)
  1117. #endif
  1118.                 {
  1119.                   msg_print("Oops! It feels deathly cold!");
  1120.                   add_inscribe(i_ptr, ID_DAMD);
  1121.                   /* To force a cost of 0, even if unidentified. */
  1122.                   i_ptr->cost = -1;
  1123.                 }
  1124.             }
  1125.             }
  1126.           else /* command == 'd' */
  1127.             {
  1128.               if (inventory[item].number > 1)
  1129.             {
  1130.               objdes(prt1, &inventory[item], TRUE);
  1131.               prt1[strlen(prt1)-1] = '?';
  1132.               (void) sprintf(prt2, "Drop all %s [y/n]", prt1);
  1133.               prt1[strlen(prt1)-1] = '.';
  1134.               prt(prt2, 0, 0);
  1135.               query = inkey();
  1136.               if (query != 'y' && query != 'n')
  1137.                 {
  1138.                   if (query != ESCAPE)
  1139.                 bell();
  1140.                   erase_line(MSG_LINE, 0);
  1141.                   item = -1;
  1142.                 }
  1143.             }
  1144.               else if (isupper((int)which) && !verify(prompt, item))
  1145.             item = -1;
  1146.               else
  1147.             query = 'y';
  1148.               if (item >= 0)
  1149.             {
  1150.               free_turn_flag = FALSE;    /* Player turn   */
  1151.               inven_drop(item, query == 'y');
  1152.               check_strength();
  1153.             }
  1154.               selecting = FALSE;
  1155.               /* As a safety measure, set the player's inven weight
  1156.              to 0, when the last object is dropped.  */
  1157.               if (inven_ctr == 0 && equip_ctr == 0)
  1158.             inven_weight = 0;
  1159.             }
  1160.           if (free_turn_flag == FALSE && scr_state == BLANK_SCR)
  1161.             selecting = FALSE;
  1162.         }
  1163.         }
  1164.     }
  1165.       if (which == ESCAPE || scr_state == BLANK_SCR)
  1166.     command = ESCAPE;
  1167.       else if (!free_turn_flag)
  1168.     {
  1169.       /* Save state for recovery if they want to call us again next turn.*/
  1170.       if (selecting)
  1171.         doing_inven = command;
  1172.       else
  1173.         doing_inven = ' ';    /* A dummy command to recover screen. */
  1174.       /* flush last message before clearing screen_change and exiting */
  1175.       msg_print(CNIL);
  1176.       screen_change = FALSE;/* This lets us know if the world changes */
  1177.       command = ESCAPE;
  1178.     }
  1179.       else
  1180.     {
  1181.       /* Put an appropriate header. */
  1182.       if (scr_state == INVEN_SCR)
  1183.         {
  1184.           if (! show_weight_flag || inven_ctr == 0)
  1185.         (void) sprintf(prt1,
  1186.             "You are carrying %d.%d pounds. In your pack there is %s",
  1187.                    inven_weight / 10, inven_weight % 10,
  1188.                    (inven_ctr == 0 ? "nothing." : "-"));
  1189.           else
  1190.         (void) sprintf (prt1,
  1191.     "You are carrying %d.%d pounds. Your capacity is %d.%d pounds. %s",
  1192.                 inven_weight / 10, inven_weight % 10,
  1193.                 weight_limit () / 10, weight_limit () % 10,
  1194.                 "In your pack is -");
  1195.           prt(prt1, 0, 0);
  1196.         }
  1197.       else if (scr_state == WEAR_SCR)
  1198.         {
  1199.           if (wear_high < wear_low)
  1200.         prt("You have nothing you could wield.", 0, 0);
  1201.           else
  1202.         prt("You could wield -", 0, 0);
  1203.         }
  1204.       else if (scr_state == EQUIP_SCR)
  1205.         {
  1206.           if (equip_ctr == 0)
  1207.         prt("You are not using anything.", 0, 0);
  1208.           else
  1209.         prt("You are using -", 0, 0);
  1210.         }
  1211.       else
  1212.         prt("Allowed commands:", 0, 0);
  1213.       erase_line(scr_base, scr_left);
  1214.       put_buffer("e/i/t/w/x/d/?/ESC:", scr_base, 60);
  1215.       command = inkey();
  1216.       erase_line(scr_base, scr_left);
  1217.     }
  1218.     }
  1219.   while (command != ESCAPE);
  1220.   if (scr_state != BLANK_SCR)
  1221.     restore_screen();
  1222.   calc_bonuses();
  1223. }
  1224.  
  1225.  
  1226. /* Get the ID of an item and return the CTR value of it    -RAK-    */
  1227. int get_item(com_val, pmt, i, j, mask, message)
  1228. int *com_val;
  1229. char *pmt;
  1230. int i, j;
  1231. char *mask;
  1232. char *message;
  1233. {
  1234.   vtype out_val;
  1235.   char which;
  1236.   register int test_flag, item;
  1237.   int full, i_scr, redraw;
  1238.  
  1239.   item = FALSE;
  1240.   redraw = FALSE;
  1241.   *com_val = 0;
  1242.   i_scr = 1;
  1243.   if (j > INVEN_WIELD)
  1244.     {
  1245.       full = TRUE;
  1246.       if (inven_ctr == 0)
  1247.     {
  1248.       i_scr = 0;
  1249.       j = equip_ctr - 1;
  1250.     }
  1251.       else
  1252.     j = inven_ctr - 1;
  1253.     }
  1254.   else
  1255.     full = FALSE;
  1256.  
  1257.   if (inven_ctr > 0 || (full && equip_ctr > 0))
  1258.     {
  1259.       do
  1260.     {
  1261.       if (redraw)
  1262.         {
  1263.           if (i_scr > 0)
  1264.         (void) show_inven (i, j, FALSE, 80, mask);
  1265.           else
  1266.         (void) show_equip (FALSE, 80);
  1267.         }
  1268.       if (full)
  1269.         (void) sprintf(out_val,
  1270.                "(%s: %c-%c,%s / for %s, or ESC) %s",
  1271.                (i_scr > 0 ? "Inven" : "Equip"), i+'a', j+'a',
  1272.                (redraw ? "" : " * to see,"),
  1273.                (i_scr > 0 ? "Equip" : "Inven"), pmt);
  1274.       else
  1275.         (void) sprintf(out_val,
  1276.                "(Items %c-%c,%s ESC to exit) %s", i+'a', j+'a',
  1277.                (redraw ? "" : " * for inventory list,"), pmt);
  1278.       test_flag = FALSE;
  1279.       prt(out_val, 0, 0);
  1280.       do
  1281.         {
  1282.           which = inkey();
  1283.           switch(which)
  1284.         {
  1285.         case ESCAPE:
  1286.           test_flag = TRUE;
  1287.           free_turn_flag = TRUE;
  1288.           i_scr = -1;
  1289.           break;
  1290.         case '/':
  1291.           if (full)
  1292.             {
  1293.               if (i_scr > 0)
  1294.             {
  1295.               if (equip_ctr == 0)
  1296.                 {
  1297.                   prt("But you're not using anything -more-",0,0);
  1298.                   (void) inkey();
  1299.                 }
  1300.               else
  1301.                 {
  1302.                   i_scr = 0;
  1303.                   test_flag = TRUE;
  1304.                   if (redraw)
  1305.                 {
  1306.                   j = equip_ctr;
  1307.                   while (j < inven_ctr)
  1308.                     {
  1309.                       j++;
  1310.                       erase_line(j, 0);
  1311.                     }
  1312.                 }
  1313.                   j = equip_ctr - 1;
  1314.                 }
  1315.               prt(out_val, 0, 0);
  1316.             }
  1317.               else
  1318.             {
  1319.               if (inven_ctr == 0)
  1320.                 {
  1321.                 prt("But you're not carrying anything -more-",0,0);
  1322.                   (void) inkey();
  1323.                 }
  1324.               else
  1325.                 {
  1326.                   i_scr = 1;
  1327.                   test_flag = TRUE;
  1328.                   if (redraw)
  1329.                 {
  1330.                   j = inven_ctr;
  1331.                   while (j < equip_ctr)
  1332.                     {
  1333.                       j++;
  1334.                       erase_line (j, 0);
  1335.                     }
  1336.                 }
  1337.                   j = inven_ctr - 1;
  1338.                 }
  1339.             }
  1340.             }
  1341.           break;
  1342.         case '*':
  1343.           if (!redraw)
  1344.             {
  1345.               test_flag = TRUE;
  1346.               save_screen();
  1347.               redraw = TRUE;
  1348.             }
  1349.           break;
  1350.         default:
  1351.           if (isupper((int)which))
  1352.             *com_val = which - 'A';
  1353.           else
  1354.             *com_val = which - 'a';
  1355.           if ((*com_val >= i) && (*com_val <= j)
  1356.               && (mask == CNIL || mask[*com_val]))
  1357.             {
  1358.               if (i_scr == 0)
  1359.             {
  1360.               i = 21;
  1361.               j = *com_val;
  1362.               do
  1363.                 {
  1364.                   while (inventory[++i].tval == TV_NOTHING);
  1365.                   j--;
  1366.                 }
  1367.               while (j >= 0);
  1368.               *com_val = i;
  1369.             }
  1370.               if (isupper((int)which) && !verify("Try", *com_val))
  1371.             {
  1372.               test_flag = TRUE;
  1373.               free_turn_flag = TRUE;
  1374.               i_scr = -1;
  1375.               break;
  1376.             }
  1377.               test_flag = TRUE;
  1378.               item = TRUE;
  1379.               i_scr = -1;
  1380.             }
  1381.           else if (message)
  1382.             {
  1383.               msg_print (message);
  1384.               /* Set test_flag to force redraw of the question.  */
  1385.               test_flag = TRUE;
  1386.             }
  1387.           else
  1388.             bell();
  1389.           break;
  1390.         }
  1391.         }
  1392.       while (!test_flag);
  1393.     }
  1394.       while (i_scr >= 0);
  1395.       if (redraw)
  1396.     restore_screen();
  1397.       erase_line(MSG_LINE, 0);
  1398.     }
  1399.   else
  1400.     prt("You are not carrying anything.", 0, 0);
  1401.   return(item);
  1402. }
  1403.  
  1404. /* I may have written the town level code, but I'm not exactly     */
  1405. /* proud of it.     Adding the stores required some real slucky     */
  1406. /* hooks which I have not had time to re-think.         -RAK-     */
  1407.  
  1408. /* Returns true if player has no light            -RAK-    */
  1409. int no_light()
  1410. {
  1411.   register cave_type *c_ptr;
  1412.  
  1413.   c_ptr = &cave[char_row][char_col];
  1414.   if (!c_ptr->tl && !c_ptr->pl)
  1415.     return TRUE;
  1416.   return FALSE;
  1417. }
  1418.  
  1419.  
  1420. /* map rogue_like direction commands into numbers */
  1421. static char map_roguedir(comval)
  1422. register char comval;
  1423. {
  1424.   switch(comval)
  1425.     {
  1426.     case 'h':
  1427.       comval = '4';
  1428.       break;
  1429.     case 'y':
  1430.       comval = '7';
  1431.       break;
  1432.     case 'k':
  1433.       comval = '8';
  1434.       break;
  1435.     case 'u':
  1436.       comval = '9';
  1437.       break;
  1438.     case 'l':
  1439.       comval = '6';
  1440.       break;
  1441.     case 'n':
  1442.       comval = '3';
  1443.       break;
  1444.     case 'j':
  1445.       comval = '2';
  1446.       break;
  1447.     case 'b':
  1448.       comval = '1';
  1449.       break;
  1450.     case '.':
  1451.       comval = '5';
  1452.       break;
  1453.     }
  1454.   return(comval);
  1455. }
  1456.  
  1457.  
  1458. /* Prompts for a direction                -RAK-    */
  1459. /* Direction memory added, for repeated commands.  -CJS */
  1460. int get_dir(prompt, dir)
  1461. char *prompt;
  1462. int *dir;
  1463. {
  1464.   char command;
  1465.   int save;
  1466.   static char prev_dir;        /* Direction memory. -CJS- */
  1467.  
  1468.   if (default_dir)    /* used in counted commands. -CJS- */
  1469.     {
  1470.       *dir = prev_dir;
  1471.       return TRUE;
  1472.     }
  1473.   if (prompt == CNIL)
  1474.     prompt = "Which direction?";
  1475.   for (;;)
  1476.     {
  1477.       save = command_count;    /* Don't end a counted command. -CJS- */
  1478. #ifdef MAC
  1479.       if (!get_comdir(prompt, &command))
  1480. #else
  1481.       if (!get_com(prompt, &command))
  1482. #endif
  1483.     {
  1484.       free_turn_flag = TRUE;
  1485.       return FALSE;
  1486.     }
  1487.       command_count = save;
  1488.       if (rogue_like_commands)
  1489.     command = map_roguedir(command);
  1490.       if (command >= '1' && command <= '9' && command != '5')
  1491.     {
  1492.       prev_dir = command - '0';
  1493.       *dir = prev_dir;
  1494.       return TRUE;
  1495.     }
  1496.       bell();
  1497.     }
  1498. }
  1499.  
  1500.  
  1501.  
  1502. /* Similar to get_dir, except that no memory exists, and it is        -CJS-
  1503.    allowed to enter the null direction. */
  1504. int get_alldir(prompt, dir)
  1505. char *prompt;
  1506. int *dir;
  1507. {
  1508.   char command;
  1509.  
  1510.   for(;;)
  1511.     {
  1512. #ifdef MAC
  1513.       if (!get_comdir(prompt, &command))
  1514. #else
  1515.       if (!get_com(prompt, &command))
  1516. #endif
  1517.     {
  1518.       free_turn_flag = TRUE;
  1519.       return FALSE;
  1520.     }
  1521.       if (rogue_like_commands)
  1522.     command = map_roguedir(command);
  1523.       if (command >= '1' && command <= '9')
  1524.     {
  1525.       *dir = command - '0';
  1526.       return TRUE;
  1527.     }
  1528.       bell();
  1529.     }
  1530. }
  1531.  
  1532.  
  1533. /* Moves creature record from one space to another    -RAK-    */
  1534. void move_rec(y1, x1, y2, x2)
  1535. register int y1, x1, y2, x2;
  1536. {
  1537.   int tmp;
  1538.  
  1539.   /* this always works correctly, even if y1==y2 and x1==x2 */
  1540.   tmp = cave[y1][x1].cptr;
  1541.   cave[y1][x1].cptr = 0;
  1542.   cave[y2][x2].cptr = tmp;
  1543. }
  1544.  
  1545.  
  1546. /* Room is lit, make it appear                -RAK-    */
  1547. void light_room(y, x)
  1548. int y, x;
  1549. {
  1550.   register int i, j, start_col, end_col;
  1551.   int tmp1, tmp2, start_row, end_row;
  1552.   register cave_type *c_ptr;
  1553.   int tval;
  1554.  
  1555.   tmp1 = (SCREEN_HEIGHT/2);
  1556.   tmp2 = (SCREEN_WIDTH /2);
  1557.   start_row = (y/tmp1)*tmp1;
  1558.   start_col = (x/tmp2)*tmp2;
  1559.   end_row = start_row + tmp1 - 1;
  1560.   end_col = start_col + tmp2 - 1;
  1561.   for (i = start_row; i <= end_row; i++)
  1562.     for (j = start_col; j <= end_col; j++)
  1563.       {
  1564.     c_ptr = &cave[i][j];
  1565.     if (c_ptr->lr && ! c_ptr->pl)
  1566.       {
  1567.         c_ptr->pl = TRUE;
  1568.         if (c_ptr->fval == DARK_FLOOR)
  1569.           c_ptr->fval = LIGHT_FLOOR;
  1570.         if (! c_ptr->fm && c_ptr->tptr != 0)
  1571.           {
  1572.         tval = t_list[c_ptr->tptr].tval;
  1573.         if (tval >= TV_MIN_VISIBLE && tval <= TV_MAX_VISIBLE)
  1574.           c_ptr->fm = TRUE;
  1575.           }
  1576.         print(loc_symbol(i, j), i, j);
  1577.       }
  1578.       }
  1579. }
  1580.  
  1581.  
  1582. /* Lights up given location                -RAK-    */
  1583. void lite_spot(y, x)
  1584. register int y, x;
  1585. {
  1586.   if (panel_contains(y, x))
  1587.     print(loc_symbol(y, x), y, x);
  1588. }
  1589.  
  1590.  
  1591. /* Normal movement                    */
  1592. /* When FIND_FLAG,  light only permanent features    */
  1593. static void sub1_move_light(y1, x1, y2, x2)
  1594. register int x1, x2;
  1595. int y1, y2;
  1596. {
  1597.   register int i, j;
  1598.   register cave_type *c_ptr;
  1599.   int tval, top, left, bottom, right;
  1600.  
  1601.   if (light_flag)
  1602.     {
  1603.       for (i = y1-1; i <= y1+1; i++)       /* Turn off lamp light    */
  1604.     for (j = x1-1; j <= x1+1; j++)
  1605.       cave[i][j].tl = FALSE;
  1606.       if (find_flag && !find_prself)
  1607.     light_flag = FALSE;
  1608.     }
  1609.   else if (!find_flag || find_prself)
  1610.     light_flag = TRUE;
  1611.  
  1612.   for (i = y2-1; i <= y2+1; i++)
  1613.     for (j = x2-1; j <= x2+1; j++)
  1614.       {
  1615.     c_ptr = &cave[i][j];
  1616.     /* only light up if normal movement */
  1617.     if (light_flag)
  1618.       c_ptr->tl = TRUE;
  1619.     if (c_ptr->fval >= MIN_CAVE_WALL)
  1620.       c_ptr->pl = TRUE;
  1621.     else if (!c_ptr->fm && c_ptr->tptr != 0)
  1622.       {
  1623.         tval = t_list[c_ptr->tptr].tval;
  1624.         if ((tval >= TV_MIN_VISIBLE) && (tval <= TV_MAX_VISIBLE))
  1625.           c_ptr->fm = TRUE;
  1626.       }
  1627.       }
  1628.  
  1629.   /* From uppermost to bottom most lines player was on.     */
  1630.   if (y1 < y2)
  1631.     {
  1632.       top = y1 - 1;
  1633.       bottom = y2 + 1;
  1634.     }
  1635.   else
  1636.     {
  1637.       top = y2 - 1;
  1638.       bottom = y1 + 1;
  1639.     }
  1640.   if (x1 < x2)
  1641.     {
  1642.       left = x1 - 1;
  1643.       right = x2 + 1;
  1644.     }
  1645.   else
  1646.     {
  1647.       left = x2 - 1;
  1648.       right = x1 + 1;
  1649.     }
  1650.   for (i = top; i <= bottom; i++)
  1651.     for (j = left; j <= right; j++)   /* Leftmost to rightmost do*/
  1652.       print(loc_symbol(i, j), i, j);
  1653. }
  1654.  
  1655.  
  1656. /* When blinded,  move only the player symbol.        */
  1657. /* With no light,  movement becomes involved.        */
  1658. static void sub3_move_light(y1, x1, y2, x2)
  1659. register int y1, x1;
  1660. int y2, x2;
  1661. {
  1662.   register int i, j;
  1663.  
  1664.   if (light_flag)
  1665.     {
  1666.       for (i = y1-1; i <= y1+1; i++)
  1667.     for (j = x1-1; j <= x1+1; j++)
  1668.       {
  1669.         cave[i][j].tl = FALSE;
  1670.         print(loc_symbol(i, j), i, j);
  1671.       }
  1672.       light_flag = FALSE;
  1673.     }
  1674.   else if (!find_flag || find_prself)
  1675.     print(loc_symbol(y1, x1), y1, x1);
  1676.  
  1677.   if (!find_flag || find_prself)
  1678.     print('@', y2, x2);
  1679. }
  1680.  
  1681.  
  1682. /* Package for moving the character's light about the screen     */
  1683. /* Four cases : Normal, Finding, Blind, and Nolight     -RAK-     */
  1684. void move_light(y1, x1, y2, x2)
  1685. int y1, x1, y2, x2;
  1686. {
  1687.   if (py.flags.blind > 0 || !player_light)
  1688.     sub3_move_light(y1, x1, y2, x2);
  1689.   else
  1690.     sub1_move_light(y1, x1, y2, x2);
  1691. }
  1692.  
  1693.  
  1694. /* Something happens to disturb the player.        -CJS-
  1695.    The first arg indicates a major disturbance, which affects search.
  1696.    The second arg indicates a light change. */
  1697. void disturb(s, l)
  1698. int s, l;
  1699. {
  1700.   command_count = 0;
  1701.   if (s && (py.flags.status & PY_SEARCH))
  1702.     search_off();
  1703.   if (py.flags.rest != 0)
  1704.     rest_off();
  1705.   if (l || find_flag)
  1706.     {
  1707.       find_flag = FALSE;
  1708.       check_view();
  1709.     }
  1710.   flush();
  1711. }
  1712.  
  1713.  
  1714. /* Search Mode enhancement                -RAK-    */
  1715. void search_on()
  1716. {
  1717.   change_speed(1);
  1718.   py.flags.status |= PY_SEARCH;
  1719.   prt_state();
  1720.   prt_speed();
  1721.   py.flags.food_digested++;
  1722. }
  1723.  
  1724. void search_off()
  1725. {
  1726. #ifdef ATARIST_MWC
  1727.   int32u holder;
  1728. #endif
  1729.  
  1730.   check_view();
  1731.   change_speed(-1);
  1732. #ifdef ATARIST_MWC
  1733.   py.flags.status &= ~(holder = PY_SEARCH);
  1734. #else
  1735.   py.flags.status &= ~PY_SEARCH;
  1736. #endif
  1737.   prt_state();
  1738.   prt_speed();
  1739.   py.flags.food_digested--;
  1740. }
  1741.  
  1742.  
  1743. /* Resting allows a player to safely restore his hp    -RAK-    */
  1744. void rest()
  1745. {
  1746.   int rest_num;
  1747.   vtype rest_str;
  1748.  
  1749.   if (command_count > 0)
  1750.     {
  1751.       rest_num = command_count;
  1752.       command_count = 0;
  1753.     }
  1754.   else
  1755.     {
  1756.       prt("Rest for how long? ", 0, 0);
  1757.       rest_num = 0;
  1758.       if (get_string(rest_str, 0, 19, 5))
  1759.     {
  1760.       if (rest_str[0] == '*')
  1761.         rest_num = -MAX_SHORT;
  1762.       else
  1763.         rest_num = atoi(rest_str);
  1764.     }
  1765.     }
  1766.   /* check for reasonable value, must be positive number in range of a
  1767.      short, or must be -MAX_SHORT */
  1768.   if ((rest_num == -MAX_SHORT)
  1769.       || (rest_num > 0) && (rest_num < MAX_SHORT))
  1770.     {
  1771.       if (py.flags.status & PY_SEARCH)
  1772.     search_off();
  1773.       py.flags.rest = rest_num;
  1774.       py.flags.status |= PY_REST;
  1775.       prt_state();
  1776.       py.flags.food_digested--;
  1777.       prt ("Press any key to stop resting...", 0, 0);
  1778.       put_qio();
  1779.     }
  1780.   else
  1781.     {
  1782.       if (rest_num != 0)
  1783.     msg_print ("Invalid rest count.");
  1784.       erase_line(MSG_LINE, 0);
  1785.       free_turn_flag = TRUE;
  1786.     }
  1787. }
  1788.  
  1789. void rest_off()
  1790. {
  1791. #ifdef ATARIST_MWC
  1792.   int32u holder;
  1793. #endif
  1794.  
  1795.   py.flags.rest = 0;
  1796. #ifdef ATARIST_MWC
  1797.   py.flags.status &= ~(holder = PY_REST);
  1798. #else
  1799.   py.flags.status &= ~PY_REST;
  1800. #endif
  1801.   prt_state();
  1802.   msg_print(CNIL); /* flush last message, or delete "press any key" message */
  1803.   py.flags.food_digested++;
  1804. }
  1805.  
  1806.  
  1807. /* Attacker's level and plusses,  defender's AC        -RAK-    */
  1808. int test_hit(bth, level, pth, ac, attack_type)
  1809. int bth, level, pth, ac, attack_type;
  1810. {
  1811.   register int i, die;
  1812.  
  1813.   disturb (1, 0);
  1814.   i = bth + pth * BTH_PLUS_ADJ
  1815.     + (level * class_level_adj[py.misc.pclass][attack_type]);
  1816.   /* pth could be less than 0 if player wielding weapon too heavy for him */
  1817.   /* always miss 1 out of 20, always hit 1 out of 20 */
  1818.   die = randint (20);
  1819.   if ((die != 1) && ((die == 20)
  1820.              || ((i > 0) && (randint (i) > ac))))  /* normal hit */
  1821.     return TRUE;
  1822.   else
  1823.     return FALSE;
  1824. }
  1825.  
  1826.  
  1827. /* Decreases players hit points and sets death flag if necessary*/
  1828. /*                             -RAK-     */
  1829. void take_hit(damage, hit_from)
  1830. int damage;
  1831. char *hit_from;
  1832. {
  1833.   if (py.flags.invuln > 0)  damage = 0;
  1834.   py.misc.chp -= damage;
  1835.   if (py.misc.chp < 0)
  1836.     {
  1837.       if (!death)
  1838.     {
  1839.       death = TRUE;
  1840.       (void) strcpy(died_from, hit_from);
  1841.       total_winner = FALSE;
  1842.     }
  1843.       new_level_flag = TRUE;
  1844.     }
  1845.   else
  1846.     prt_chp();
  1847. }
  1848.